home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / dev / tm.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  7KB  |  301 lines

  1. #ifndef    M25
  2.  
  3. #ifndef lint
  4. /* static    char sccsid[] = "@(#)tm.c 1.1 86/09/27 Copyr 1986 Sun Micro"; */
  5. #endif
  6.  
  7. /*
  8.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  9.  */
  10.  
  11. /*
  12.  * Standalone driver for Ciprico TapeMaster Multibus tape controller
  13.  */
  14.  
  15. #include "../dev/saio.h"
  16. #include "../dev/tmreg.h"
  17. #include "../sun3/cpu.addrs.h"
  18.  
  19. /*
  20.  * Standard addresses for this board
  21.  */
  22. #define NTMADDR    2
  23. unsigned long tmstd[] = { 0xA0, 0xA2 };
  24.  
  25. /*
  26.  * Structure of our dma space
  27.  */
  28. #define MAXTMREC    (20*1024)    /* max size tape rec allowed */
  29. struct tmdma {
  30.     struct tm_mbinfo tm_mbinfo;    /* Multibus IOPB crap */
  31.     char        tmbuf[MAXTMREC];/* Block of data */
  32. };
  33.  
  34. #define    MB_DMA_ADDR_MASK    0x000FFFFF    /* Low meg */
  35.  
  36.  
  37. /*
  38.  * Driver's local variables
  39.  */
  40. struct tmparam {
  41.     unsigned char    tmeof;        /* Remembers EOF */
  42. };
  43.  
  44. /*
  45.  * Driver definition
  46.  */
  47. struct devinfo tminfo = {
  48.     sizeof(struct tmdevice),    /* Size of device registers */
  49.     sizeof(struct tmdma),        /* DMA space required */
  50.     sizeof(struct tmparam),        /* Local variable space */
  51.     NTMADDR,            /* # of standard addresses */
  52.     tmstd,                /* Standard addr vector */
  53.     MAP_MBIO,            /* Map type of device regs */
  54. };
  55.  
  56. /*
  57.  * What facilities we export to the world
  58.  */
  59. int    tmstrategy(), tmopen(), tmclose();
  60. extern int      nullsys(), ttboot();
  61.  
  62. struct boottab mtdriver = {
  63.     "mt", nullsys, ttboot, tmopen, tmclose, tmstrategy,
  64.     "mt: TapeMaster 9-track tape", &tminfo,
  65. };
  66.  
  67.  
  68. /*
  69.  * Open a tape drive
  70.  */
  71. tmopen(sip)
  72.     register struct saioreq *sip;
  73. {
  74.     register skip;
  75.  
  76.     if (tminit(sip) == -1)
  77.         return (-1);
  78.     ((struct tmparam *)sip->si_devdata)->tmeof = 0;
  79.     tmcmd(sip, TM_REWINDX);
  80.     skip = sip->si_boff;
  81.     while (skip--) {
  82.         sip->si_cc = 0;
  83.         tmcmd(sip, TM_SEARCH);
  84.     }
  85.     return (0);
  86. }
  87.  
  88. tmclose(sip)
  89.     struct saioreq *sip;
  90. {
  91.  
  92.     ((struct tmparam *)sip->si_devdata)->tmeof = 0;
  93.     tmcmd(sip, TM_REWINDX);
  94. }
  95.  
  96. tmstrategy(sip, rw)
  97.     register struct saioreq *sip;
  98.     int rw;
  99. {
  100.     int func = (rw == WRITE) ? TM_WRITE : TM_READ;
  101.     register int n, occ, cc;
  102.     char *oma;
  103.  
  104.     cc = occ = sip->si_cc;
  105.     oma = sip->si_ma;
  106.  
  107.     if (((struct tmparam *)sip->si_devdata)->tmeof) {
  108.         ((struct tmparam *)sip->si_devdata)->tmeof = 0;
  109.         return (0);
  110.     }
  111.     while (cc > 0) {
  112.         if (cc > MAXTMREC)
  113.             sip->si_cc = MAXTMREC;
  114.         else
  115.             sip->si_cc = cc;
  116.         n = tmcmd(sip, func);
  117.         if (n <= 0)
  118.             break;
  119.         sip->si_ma += n;
  120.         cc -= n;
  121.     }
  122.     if (n == -1)
  123.         return (-1);
  124.     if (n == 0 && cc != occ)
  125.         ((struct tmparam *)sip->si_devdata)->tmeof = 1;
  126.     if (cc < 0)
  127.         cc = 0;
  128.     n = occ - cc;
  129.     sip->si_cc = occ;
  130.     sip->si_ma = oma;
  131.     return (n);
  132. }
  133.  
  134. #define NOTZERO    1    /* don't care value-but not zero (clr inst botch) */
  135. #define ATTN(c)     (((struct tmdevice *)c)->tmdev_attn=NOTZERO)
  136. #define RESET(c)     (((struct tmdevice *)c)->tmdev_reset=NOTZERO)
  137. #define clrtpb(tp)    bzero((caddr_t)(tp), sizeof *(tp));
  138.  
  139. tmcmd(sip, func)
  140.     register struct saioreq *sip;
  141. {
  142. #    define    tmdmap    ((struct tmdma *)sip->si_dmaaddr)
  143. #    define    tmb    (&tmdmap->tm_mbinfo)
  144.     register struct tmdevice *tmaddr =
  145.         (struct tmdevice *)sip->si_devaddr;
  146.     register struct tpb *tpb = &tmb->tmb_tpb;
  147.     int count = 1;
  148.     int size = 0;
  149.     struct tmstat tms;
  150.     int err;
  151.  
  152.     switch (func) {
  153.  
  154.     case TM_READ:
  155.         size = sip->si_cc;
  156.         break;
  157.  
  158.     case TM_WRITE:
  159.         size = sip->si_cc;
  160.         swab((char *)sip->si_ma, tmdmap->tmbuf, size);
  161.         break;
  162.     }
  163.  
  164.     clrtpb(tpb);
  165.     tpb->tm_cmd = func &~ TM_DIRBIT;
  166.     tpb->tm_ctl.tmc_rev = func & TM_DIRBIT;
  167.     tpb->tm_ctl.tmc_width = 1;
  168.     tpb->tm_ctl.tmc_speed = sip->si_unit & 08;
  169.     tpb->tm_ctl.tmc_tape = sip->si_unit & 03;
  170.     tpb->tm_rcount = count;
  171.     tpb->tm_bsize = size;
  172.     c68t86((long)tmdmap->tmbuf, &tpb->tm_baddr);
  173.     tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
  174.  
  175.     /* Start the command and wait for completion */
  176.     ATTN(tmaddr);
  177.     while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
  178.         ;
  179.  
  180.     tms = tpb->tm_stat;
  181.     err = tms.tms_error;
  182.  
  183.     /*
  184.      * An operation completed... record status
  185.      */
  186.     if (err == E_EOT && tms.tms_load)
  187.         err = E_NOERROR;
  188.     /*
  189.      * Check for errors.
  190.      */
  191.     if (err != E_NOERROR && err != E_SHORTREC) {
  192.         if (err == E_EOF || err == E_EOT)
  193.             return (0);
  194.         /* Note: TapeMaster does retries for us */
  195.         printf("tm hard err %x\n", err);
  196.         return (-1);
  197.     }
  198.     if (func == TM_READ)
  199.         swab(tmdmap->tmbuf, sip->si_ma, tpb->tm_count);
  200.     return (tpb->tm_count);
  201. #    undef    tmdma
  202. #    undef    tmb
  203. }
  204.  
  205. #define SPININIT 1000000
  206. /*
  207.  * Initialize a controller
  208.  * Reset it, set up SCP, SCB, and CCB,
  209.  * and give it an attention.
  210.  * Make sure its there by waiting for the gate to open
  211.  * Once initialization is done, issue CONFIG just to be safe.
  212.  */
  213. tminit(sip)
  214.     register struct saioreq *sip;
  215. {
  216.     register struct tm_mbinfo *tmb = 
  217.         &((struct tmdma *)(sip->si_dmaaddr))->tm_mbinfo;
  218.     register struct tmdevice *tmaddr =
  219.         (struct tmdevice *)sip->si_devaddr;
  220.     register struct tpb *tpb = &tmb->tmb_tpb;
  221.  
  222.     bzero((caddr_t)tmb, sizeof (struct tm_mbinfo));
  223.     RESET(tmaddr);
  224.     
  225.     /* setup System Configuration Block */
  226.     tmb->tmb_scb.tmscb_03 = tmb->tmb_scb.tmscb_03x = TMSCB_CONS;
  227.     c68t86((long)&tmb->tmb_ccb, &tmb->tmb_scb.tmccb_ptr);
  228.  
  229.     /* setup Channel Control Block */
  230.     tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
  231.  
  232.     {
  233.         register struct tmscp *tmscp;
  234.         struct tmscp dummyscp;
  235.         register int spin;
  236.  
  237.         tmscp = (struct tmscp *)(DVMA_BASE + TM_SCPADDR);
  238.  
  239.         /* setup System Configuration Pointer */
  240.         tmscp->tmscb_bus = tmscp->tmscb_busx = TMSCB_BUS16;
  241.         c68t86((long)&tmb->tmb_scb, &tmscp->tmscb_ptr);
  242.  
  243.         /* Start the TapeMaster and wait til it says "done" */
  244.         ATTN(tmaddr); 
  245.         for (spin = SPININIT; tmb->tmb_ccb.tmccb_gate != TMG_OPEN; )
  246.             if (--spin <= 0)
  247.                 break;
  248.  
  249.         if (spin <= 0) {
  250.             printf("tm: no response from ctlr %x\n", sip->si_ctlr);
  251.             return (-1);
  252.         }
  253.     }
  254.  
  255.     /* Finish CCB, point it at TPB */
  256.     tmb->tmb_ccb.tmccb_ccw = TMC_NORMAL;
  257.     c68t86((long)tpb, &tmb->tmb_ccb.tmtpb_ptr);
  258.  
  259.     /* Issue CONFIG command */
  260.     clrtpb(tpb);
  261.     tpb->tm_cmd = TM_CONFIG;
  262.     tpb->tm_cmd2 = 0;
  263.     tpb->tm_ctl.tmc_width = 1;
  264.  
  265.     /* Get the gate */
  266.     while (tmb->tmb_ccb.tmccb_gate != TMG_OPEN)
  267.         ;
  268.     tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
  269.  
  270.     /* Start the command and wait for completion */
  271.     ATTN(tmaddr);
  272.     while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
  273.         ;
  274.  
  275.     /* Check and report errors */
  276.     if (tpb->tm_stat.tms_error) {
  277.         printf("tm: error %d during config of ctlr %x\n", 
  278.             tpb->tm_stat.tms_error, sip->si_ctlr);
  279.         tpb->tm_stat.tms_error = 0;
  280.         return (-1);
  281.     }
  282.     return (0);
  283. }
  284.  
  285. /*
  286.  * Convert a 68000 address into a 8086 address
  287.  * This involves translating a virtual address into a
  288.  * physical multibus address and converting the 20 bit result
  289.  * into a two word base and offset.
  290.  */
  291. static c68t86(a68, a86)
  292.     long a68;
  293.     ptr86_t *a86;
  294. {
  295.  
  296.     a68 &= MB_DMA_ADDR_MASK;
  297.     a86->a_offset = a68 & 0xFFFF;
  298.     a86->a_base = (a68 & 0xF0000) >> 4;
  299. }
  300. #endif    M25
  301.